package org.wsdltools.profiles.wsi

import org.wsdltools.common.model.MEPEnum;
import org.wsdltools.common.model.ServiceInteraction;
import org.wsdltools.common.model.ProfileEnum;
import org.wsdltools.common.model.Operation;

class WSDLGenerator {
	public String generateWSDL(ServiceInteraction si) {
		use (ServiceInteractionWsdlDSL, OperationWsdlDSL) {
			
			StringWriter wsdl = new StringWriter()
			def xmlBuilder = new groovy.xml.MarkupBuilder(wsdl)
			
			// Create map of namespace alias declarations
			def rootElementAttributes = [
					name: "${si.name}Interaction",
					'xmlns:wsdl': 'http://schemas.xmlsoap.org/wsdl/',
					'xmlns:soap': 'http://schemas.xmlsoap.org/wsdl/soap/',
					'xmlns:xs': 'http://www.w3.org/2001/XMLSchema',
					'xmlns:tjsr': si.responderServiceSchemaTargetNamespace,
					'xmlns:tjsi': si.initiatorServiceSchemaTargetNamespace,
					'xmlns:tns': si.wsdlTargetNamespace,
					targetNamespace: si.wsdlTargetNamespace]
	
			
			xmlBuilder.'wsdl:definitions'(rootElementAttributes) {
				
				'xs:annotation' {
					'xs:documentation' (
							"""
			 Tjänsteinteraktionens namn: ${si.name}Interaction
			 Beskrivning: 
			   ${si.description}
			 Revisioner: 
			 Tjänstedomän: ${si.serviceDomain}
			 Tjänsteinteraktionstyp: ${si.interactionTypeDescription}
			 WS-profil: ${si.profile}
			 Förvaltas av: xxx
			 """)
				}
				
				'wsdl:types' {
					// Import responder schema
					'xs:schema'(targetNamespace : si.responderServiceSchemaTargetNamespace) {   
						// Import the responder service schema 
						'xs:import' (schemaLocation : "${si.responderSchemaName}", namespace : si.responderServiceSchemaTargetNamespace)
					}
					// Import initiator schema if service interaction type is BiDir (Uppdrag-Resultat)
					if (si.isBiDir) {
						'xs:schema' (targetNamespace : si.initiatorServiceSchemaTargetNamespace){   
							// Import the responder service schema 
							'xs:import' (schemaLocation : "${si.initiatorSchemaName}", namespace : si.initiatorServiceSchemaTargetNamespace)
						}
					}
					// import ws-addressing
					if (si.profile == ProfileEnum.RIVTABP20) {
						'xs:schema'(targetNamespace : "http://www.w3.org/2005/08/addressing") {   
							// Import the responder service schema 
							'xs:import' (schemaLocation : "../../core_components/ws-addressing-1.0.xsd", namespace : "http://www.w3.org/2005/08/addressing")
						}
					}
				}
				
				// Produce Message elements for responder request + ev. response and ev. the same for initiator
				si.operations.each {Operation operation ->
					'wsdl:message'(name : operation.inputMessageName) {
						if (si.profile == ProfileEnum.RIVTABP20) {
							'wsdl:part'(name : 'LogicalAddress', element : "wsa:To") {
								'xs:annotation' {
									'xs:documentation' (operation.serviceInteraction.logicalAddressDescription)
								}
							}
						}
						'wsdl:part'(name : 'parameters', element : "${operation.inputElementName}")
					}
					if (operation.mep == MEPEnum.InOut) {
						'wsdl:message'(name : operation.outputMessageName) {
							'wsdl:part'(name : 'parameters', element : "${operation.outputElementName}")
						}
					}
				}
				
				si.operations.each {Operation operation ->
					'wsdl:portType'(name : operation.portType) {
						'wsdl:operation'(name : operation.name) {
							'wsdl:input'(message : "tns:${operation.inputMessageName}")
							if (operation.mep == MEPEnum.InOut) {
								'wsdl:output'(message : "tns:${operation.outputMessageName}")
							}
						}
					}
				}
				
				// The concrete binding section for responder and eventually initiator service ports
				
				si.operations.each {Operation operation ->
					'wsdl:binding'(name : operation.bindingName, type : "tns:${operation.portType}") {
						'soap:binding'(style : "document", transport : "http://schemas.xmlsoap.org/soap/http")
						'wsdl:operation'(name : "${operation.name}") {
							'soap:operation'(soapAction : operation.soapAction, style : "document")
							'wsdl:input' {
								if (si.profile == ProfileEnum.RIVTABP20) {
									'soap:header'(use : "literal", message : "tns:${operation.inputMessageName}", part : "LogicalAddress")
								}
								'soap:body'(use : "literal", parts : "parameters")
							}
							if (operation.mep == MEPEnum.InOut) {
								'wsdl:output' {
									'soap:body'(use : "literal")
								}
							}
						}
					}
				}
				// The concrete service port section. All services are published by the port of the
				// service gateway for the specified deployment context
				si.operations.each {Operation operation -> 
					'wsdl:service'(name : operation.serviceName) {	
						'wsdl:port'(name : operation.portName,
								binding : "tns:${operation.bindingName}") { 'soap:address'(location : "http://tempuri.org") }
					}
				}
			}
			
			return "${GeneratorUtil.xmlPrologue}${GeneratorUtil.licenseDeclaration}${wsdl}"
		}
	}
}
